package org.korosoft.rusalad.syncnrun.command;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.korosoft.rusalad.syncnrun.messaging.Message;
import org.korosoft.rusalad.syncnrun.messaging.MessageRoute;
import org.korosoft.rusalad.syncnrun.messaging.Messenger;

import java.io.File;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

/**
 * Syncnrun "upload files" RPC command.
 *
 * @author Dmitry Korotkov
 * @since 1.0
 */
public class SyncLocalDirCmd extends AbstractSyncCmd<SyncLocalDirCmd.SyncLocalDirAnswer> {
    private static final Log log = LogFactory.getLog(SyncLocalDirCmd.class);

    private final UUID messagingRouteName;
    private final String targetPath;
    private final boolean singleFileTransfer;
    private final List<AbstractSyncCmd.FileInfo> sourceFiles;

    private final transient File sourcePath;

    public SyncLocalDirCmd(String targetPath, LocalFilesInfo localFilesInfo) {
        this.sourceFiles = localFilesInfo.localFiles;
        this.targetPath = targetPath;
        this.sourcePath = localFilesInfo.localFilesPath;
        this.singleFileTransfer = localFilesInfo.singleFileTransfer;
        this.messagingRouteName = UUID.randomUUID();
    }

    @Override
    public SyncLocalDirCmd.SyncLocalDirAnswer execute(Messenger messenger) throws IOException {
        final long bytesSent;
        try {
            final MessageRoute route = messenger.getRoute(messagingRouteName);
            bytesSent = sendOutHashes(route, sourceFiles, targetPath, singleFileTransfer);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        return new SyncLocalDirCmd.SyncLocalDirAnswer(bytesSent);
    }

    @Override
    public Collection<UUID> getRouteNames() {
        return Collections.singletonList(messagingRouteName);
    }

    @Override
    public void processMessageAtClient(MessageRoute route, Message message) {
        if (!(message instanceof AbstractSyncCmd.FileHashListMsg)) {
            throw new RuntimeException("Unexpected message: " + message.getClass().getName());
        }
        processHashListMessage(route, (FileHashListMsg) message, sourceFiles, sourcePath, null);
    }

    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        for (FileInfo info : sourceFiles) {
            builder.append("\n\t");
            builder.append(info.toString());
        }
        return String.format("Send file / directory. Target path: %s. Single file transfer: %s. Source files: [%s].", targetPath, singleFileTransfer, builder.toString());
    }

    public static class SyncLocalDirAnswer implements Answer {
        public final long bytesSent;

        public SyncLocalDirAnswer(long bytesSent) {
            this.bytesSent = bytesSent;
        }

        @Override
        public String toString() {
            return "Local dir sync done";
        }
    }

}
